package cn.fzkj.annotation;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;

/**
 * @DESCRIPTION: 登陆策略选择处理器
 * @AUTHOR: yaya
 * @DATE: 2021/8/15
 */
public class LoginStrategy {

    /** 注解包 */
    private static final String path = "cn/fzkj/annotation";

    private static Map<LoginType, Login> loginMap = new HashMap<>();

    /** 模拟读取注解，加载策略的过程 */
    public static void init(){
        Set classes = new LinkedHashSet();
        try {
            Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(path);
            while(resources.hasMoreElements()){
                URL url = resources.nextElement();
                // 获取包中所有class
                String filePath = URLDecoder.decode(url.getFile(), "UTF-8");//以文件的方式扫描整个包下的文件 并添加到集合中
                findAndAddClassesInPackageByFile(path, filePath, true, classes);
                // 加载
                Iterator iterator = classes.iterator();
                while (iterator.hasNext()){
                    Class next = (Class) iterator.next();
                    Annotation[] annotations = next.getAnnotations();
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof Register){
                            try {
                                loginMap.put(((Register)annotation).value(), (Login)next.newInstance());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, Set classes) {//获取此包的目录 建立一个File

        File dir = new File(packagePath);//如果不存在或者 也不是目录就直接返回

        if (!dir.exists() || !dir.isDirectory()) {//log.warn("用户定义包名 " + packageName + " 下没有任何文件");

            return;

        }//如果存在 就获取包下的所有文件 包括目录

        File[] dirfiles = dir.listFiles(new FileFilter() {//自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)

            public boolean accept(File file) {return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));

            }

        });//循环所有文件

        for(File file : dirfiles) {//如果是目录 则继续扫描

            if(file.isDirectory()) {
                findAndAddClassesInPackageByFile(packageName+ "." +file.getName(), file.getAbsolutePath(), recursive,

                        classes);

            }else{//如果是java类文件 去掉后面的.class 只留下类名

                String className = file.getName().substring(0, file.getName().length() - 6);
                packageName = packageName.replaceAll("/", "\\.");

                try{//添加到集合中去
                    // classes.add(Class.forName(packageName + '.' + className));//经过回复同学的提醒，这里用forName有一些不好，会触发static方法，没有使用classLoader的load干净

                    classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' +className));

                }catch(ClassNotFoundException e) {//log.error("添加用户自定义视图类错误 找不到此类的.class文件");

                    e.printStackTrace();

                }

            }

        }
    }

    /** 获取策略 */
    public static Login getStrategy(LoginType type){
        return loginMap.get(type);
    }

}
